var scheduleVM;
var isInitialised = false;
var isOverUilized = false;
var scheduleVo = {
	sectionId : "",
	scheduleId : "",
	scheduleTitle : "",
	startTiming : "",
	endTiming : "",
	daysOfWeek : [],
	scheduleName : "",
	timeTable : ""

};

var scheduleViewModel = function() {
	var self = this;

	self.scheduleList = ko.observableArray();

	self.selectedItem = ko.observable();
	self.itemForEditing = ko.observable();

	self.itemForDelete = ko.observable();

	self.createItem = this.createItem.bind(this);
	self.selectItem = this.selectItem.bind(this);
	self.acceptItem = this.acceptItem.bind(this);
	self.revertItem = this.revertItem.bind(this);
	self.deleteItem = this.deleteItem.bind(this);

	/////////////////////////////////

	self.errorTitle = ko.observable();
	self.errorDesc = ko.observable();
	self.isErrorDialogOpen = ko.observable(false);

	self.openErrorDialog = function(myErrorTitle, myErrorDesc) {
		self.errorTitle(myErrorTitle);
		self.errorDesc(myErrorDesc);
		this.isErrorDialogOpen(true);

	};
	self.closeErrorDialog = function() {
		this.isErrorDialogOpen(false);
	};

	self.validateUnutilizedDuration = function() {
		var item = this.itemForEditing().unutilizedDuration();
		if (item.indexOf("-") !== -1) {
			isOverUilized = true;
			//alert("Exceded Utilization time");
			scheduleVM.openErrorDialog("Utilization Time", "Exceded Utilization time");
		} else {
			isOverUilized = false;
		}

	};

};

ko.utils.extend(scheduleViewModel.prototype, {

	createItem : function(item) {
		//console.log("creating item", this.itemForEditing());
		if (this.itemForEditing() == null) {
			this.itemForEditing(new createScheduleModel(""));

			//	callCustomInit();
		}
	},
	selectItem : function(item) {
		//console.log("selected item", item);

		this.selectedItem(item);
		this.itemForEditing(new createScheduleModel(ko.toJS(item)));

		//	callCustomInit();
		jQuery("#add-Schedule").dialog("open");
		this.itemForEditing().updateScrollPosition(false);

	},

	acceptItem : function(item) {
		var self = this;
		//console.log("accept item", this.itemForEditing());
		//console.log("selected item", this.selectedItem());

		/* Validations Start */
		var vm = ko.validation.group(this.itemForEditing());

		if (this.itemForEditing().isValid() == false) {
			vm.showAllMessages();
			//alert("Please fill all Required fields before saving.");

			scheduleVM.openErrorDialog("Required Fields", "Please fill all Required fields before saving.");
			return;
		}

		/**
		 * Duration should be greater than Zero.
		 */

		if (this.itemForEditing().timeTable().length > 0) {
			var isDurationValid = true;
			for (var i = 0; i < this.itemForEditing().timeTable().length; i++) {
				var periodBreakModel = this.itemForEditing().timeTable()[i];

				if (periodBreakModel.duration() < 1) {
					isDurationValid = false;
				};

			}

			if (!isDurationValid) {
				//alert("Please fill all Required fields before saving.");
				scheduleVM.openErrorDialog("Duration", "Duration should be greater than Zero.");
				return;
			}
		}

		/**
		 * Please select any Exceptions.
		 * Please fill all Required fields before saving.
		 *
		 */
		if (this.itemForEditing().weekExceptions().length > 0) {
			var isValid = true;
			for (var i = 0; i < this.itemForEditing().weekExceptions().length; i++) {

				//Select any of the Check Boxes
				var WE = this.itemForEditing().weekExceptions()[i];
				if (WE.every() || WE.first() || WE.second() || WE.third() || WE.fourth() || WE.fifth()) {
					//if any one checked ok
				} else {
					isValid = false;
					//alert("Please select any Exceptions.");
					scheduleVM.openErrorDialog("Exceptions", "Please select any Exceptions.");
					return;
				}

				//Select the Day Combo
				var vm1 = ko.validation.group(this.itemForEditing().weekExceptions()[i]);
				if (vm1().length != 0) {
					vm1.showAllMessages();
					isValid = false;
				}

			}

			if (!isValid) {
				//alert("Please fill all Required fields before saving.");
				scheduleVM.openErrorDialog("Required Fields", "Please fill all Required fields before saving.");
				return;
			}
		}

		for (var j = 0; j < this.scheduleList().length; j++) {
			if ((this.scheduleList()[j].scheduleTitle() == this.itemForEditing().scheduleTitle()) && (this.scheduleList()[j].scheduleId() != this.itemForEditing().scheduleId())) {
				//alert("Schedule title Already Exists, Please Modify");
				scheduleVM.openErrorDialog("Schedule Title Already Exists", "Schedule title Already Exists, Please Modify");
				return;
			}
		}

		if (isOverUilized) {// Check for Over Utilization
			//alert("Periods over Utilized");
			scheduleVM.openErrorDialog("Periods", "Periods over Utilized");
			return;
		}

		if (this.itemForEditing().daysOfWeek().length <= 0) {
			//alert("Minimum one Applicable day required");
			scheduleVM.openErrorDialog("Days", "Minimum one Applicable day required");
			return;
		}

		$("#add-Schedule").dialog("close");

		/* Validations End */

		var mapping = {
			'ignore' : ["isSelected", "periodOptions", "fullTiming", "title", "weekDays", "daysStr", "noOfPeriods", "noOfBreaks", "noOfStarStudyPeriod", "extraSno", "totalDuration", "computedDay", "unutilizedDuration", "errors"]
		};

		var jsonData = ko.mapping.toJSON(this.itemForEditing(), mapping);
		//console.log("------>", jsonData);

		showLoader(true, TYPE_SAVING);
		jQuery.ajax({
			data : {
				savedata : jsonData
			},
			url : baseOperationUrl + "saveSecPlanSchedule",
			type : "post",
			success : function(result) {
				//console.log("result", result);
				//console.log("scheduleVM", scheduleVM);
				//console.log("self", self);

				if (self.selectedItem() == undefined) {
					self.itemForEditing().scheduleId(result.scheduleId);
					//console.log("adding schedule", self.itemForEditing());
					self.scheduleList.push(self.itemForEditing());

				} else {
					//console.log("edit schedule");
					var selected = self.selectedItem();
					edited = ko.toJS(self.itemForEditing());
					selected.update(edited);
				}

				self.selectedItem(null);
				self.itemForEditing(null);

				showLoader(false);

			},
			error : function(jqXHR, textStatus, errorThrown) {
				//console.log("error");
				self.selectedItem(null);
				self.itemForEditing(null);
				//showLoader(false);
			}
		});

	},
	revertItem : function() {
		//console.log("close");
		this.selectedItem(null);
		this.itemForEditing(null);

		$("#add-Schedule").dialog("close");

	},
	deleteItem : function(item) {
		//console.log("deleting schedule", this.itemForDelete());
		var deleteVM = new deleteViewModel();
		deleteVM.currentItem(item);
		deleteVM.parentItem(this);

		this.itemForDelete(deleteVM);
		$("#dialog-confirmScheduleDelete").dialog("open");

	}
});

var createScheduleModel = function(data, scheduleList) {
	var self = this;

	self.sectionId = ko.observable();
	self.scheduleId = ko.observable();
	self.scheduleTitle = ko.observable('').extend({
		required : true
	});
	self.startTiming = ko.observable().extend({
		required : true
	});
	self.endTiming = ko.observable().extend({
		required : true
	});

	/** BO Split hour minute spinner */
	//
	self.startTiming.hour = ko.observable();
	self.startTiming.minute = ko.observable();
	self.endTiming.hour = ko.observable();
	self.endTiming.minute = ko.observable();

	var tempST;
	var tempET;
	if (data.startTiming) {
		tempST = data.startTiming;
		tempET = data.endTiming;
	} else {
		data.startTiming = "06:00";
		data.endTiming = "16:00";

		tempST = "06:00";
		tempET = "16:00";
	};
	var startTimeArr = tempST.split(":");
	self.startTiming.hour(startTimeArr[0]);
	self.startTiming.minute(startTimeArr[1]);

	var endTimeArr = tempET.split(":");
	self.endTiming.hour(endTimeArr[0]);
	self.endTiming.minute(endTimeArr[1]);

	//
	function updateStartTime() {
		//make it 2 digit based.
		self.startTiming.hour(("0" + self.startTiming.hour()).slice(-2));
		self.startTiming.minute(("0" + self.startTiming.minute()).slice(-2));

		self.startTiming(self.startTiming.hour() + ":" + self.startTiming.minute());
	};
	function updateEndTime() {
		//make it 2 digit based.
		self.endTiming.hour(("0" + self.endTiming.hour()).slice(-2));
		self.endTiming.minute(("0" + self.endTiming.minute()).slice(-2));

		self.endTiming(self.endTiming.hour() + ":" + self.endTiming.minute());
	};

	//
	self.startTiming.hour.subscribe(function(item) {
		//console.log("item :: ", item);
		updateStartTime();
	});
	self.startTiming.minute.subscribe(function(item) {
		updateStartTime();
	});
	self.endTiming.hour.subscribe(function(item) {
		updateEndTime();
	});
	self.endTiming.minute.subscribe(function(item) {
		updateEndTime();
	});

	/** EO Split hour minute spinner */

	self.fullTiming = ko.observable();
	self.weekDays = ko.observableArray();
	self.daysOfWeek = ko.observableArray().extend({
		min : {
			params : 0
		}
	});
	self.daysStr = ko.observable();
	self.timeTable = ko.observableArray().extend({
		required : true,
		minLength : 1
	});
	;
	self.periodOptions = ko.observableArray();
	self.noOfPeriods = ko.observable();
	self.noOfBreaks = ko.observable();
	self.noOfStarStudyPeriod = ko.observable();
	self.totalDuration = ko.observable();
	self.unutilizedDuration = ko.observable();
	// Will be noOfPeriods * No of daysOfWeek
	self.weekExceptions = ko.observableArray();

	self.weekExceptions.weekExceptionsStr = ko.computed(function() {

		if (!self.weekExceptions().length) {
			return "-";
		} else {
			var weekArray = new Array();
			var str = "-";
			for (var i = 0; i < self.weekExceptions().length; i++) {
				var WE = self.weekExceptions()[i];

				//	if (WE.every() || WE.first() || WE.second() || WE.third() || WE.fourth() || WE.fifth()) {

				if (WE.every()) {
					weekArray.push("every");
				}

				if (WE.first()) {
					weekArray.push("first");
				}
				if (WE.second()) {
					weekArray.push("second");
				}
				if (WE.third()) {
					weekArray.push("third");
				}
				if (WE.fourth()) {
					weekArray.push("fourth");
				}
				if (WE.fifth()) {
					weekArray.push("fifth");
				}

			};

			str = WE.day() + " (" + weekArray.toString() + ")";
			//console.log("weekExceptionsStr  :: ", str);
			return str;
		}

	});
	/**
	 *This will update the scroll position
	 * //true will animate
	 *
	 * //false will not animate and take the scroll position to top
	 * (This false fixed the xtra space coming after adding periods and canceling it and coming back.)
	 */
	self.updateScrollPosition = function(animate) {
		/**
		 *Prasanna
		 * BO Scroll the bar to borrom by some pixels animated
		 *
		 */
		var pane = $('#ScheduleData');
		pane.jScrollPane({
			showArrows : true,
			animateScroll : animate
		});
		var api = pane.data('jsp');
		//console.log("animate :: ", animate);
		if (animate) {
			api.scrollBy(2, 50);
		} else {
			api.scrollToY(0);
		};
		/**
		 * EO Scroll the bar to borrom by some pixels animated
		 */
	};

	self.addPeriod = function() {
		//console.log("-------> adding period");
		//self.timeTable.push(new periodBreakModel({sno: self.timeTable().length+1,type:"Period",duration:0}));
		self.timeTable.push(new periodBreakModel(""));
		self.updateScrollPosition(true);
	};

	self.deletePeriod = function(item) {
		//console.log("deleting period", item);
		self.timeTable.remove(item);
	};
	self.addExcpetion = function() {
		//console.log("adding exception");
		self.weekExceptions.push(new dayExceptionModel(""));
		//	callCustomInit();
	};

	self.deleteException = function(item) {
		//console.log("delete exception");

		self.weekExceptions.remove(item);
	};

	self.update(data);
};

createScheduleModel.prototype.update = function(data) {

	var self = this;

	//console.log("updating create schedule model", data);
	self.sectionId(data.sectionId || sectionId);
	self.scheduleId(data.scheduleId || "");
	self.scheduleTitle(data.scheduleTitle || "");
	self.startTiming(data.startTiming || "07:00");
	self.endTiming(data.endTiming || "15:00");
	//self.daysOfWeek(data.daysOfWeek || [{title:"M",day:'Mon',isSelected:true},{title:"T",day:'Tue',isSelected:false},{title:"W",day:'Wed',isSelected:false},{title:"T",day:'Thu',isSelected:false},{title:"F",day:'Fri',isSelected:false},{title:"S",day:'Sat',isSelected:false},{title:"S",day:'Sun',isSelected:false}]);
	//	self.daysOfWeek(data.daysOfWeek || []);
	self.timeTable([]);
	self.weekExceptions([]);
	self.periodOptions(["Period", "Break", "Star/Study Period"]);
	self.daysStr(data.daysStr || "");
	self.weekDays([new applicableDay({
		title : "M",
		day : 'Mon',
		isSelected : false
	}), new applicableDay({
		title : "T",
		day : 'Tue',
		isSelected : false
	}), new applicableDay({
		title : "W",
		day : 'Wed',
		isSelected : false
	}), new applicableDay({
		title : "T",
		day : 'Thu',
		isSelected : false
	}), new applicableDay({
		title : "F",
		day : 'Fri',
		isSelected : false
	}), new applicableDay({
		title : "S",
		day : 'Sat',
		isSelected : false
	}), new applicableDay({
		title : "S",
		day : 'Sun',
		isSelected : false
	})]);
	self.fullTiming = ko.computed(function() {

		return self.startTiming() + " to " + self.endTiming();
	});
	self.daysOfWeek = ko.computed(function() {

		var daysArr = new Array();
		var str = "";
		//console.log("--->", self.weekDays()[0].isSelected());
		for (var i = 0; i < self.weekDays().length; i++) {
			if (self.weekDays()[i].isSelected() == true) {
				daysArr.push(self.weekDays()[i]);

				if (str == "") {
					str = self.weekDays()[i].day();
				} else {
					str = str + "," + self.weekDays()[i].day();
				}
			}
		}

		self.daysStr(str);
		return daysArr;
	});

	self.noOfBreaks = ko.computed(function() {
		//console.log("Period break");
		var noOfBreaks = 0;
		var noOfPeriods = 0;
		var noOfStarStudyPeriod = 0;
		//console.log("=============================================================");
		for (var i = 0; i < self.timeTable().length; i++) {
			//console.log("self.timeTable()[i].type() :: ", self.timeTable()[i].type());
			if (self.timeTable()[i].type() == "Period") {
				noOfPeriods++;
			} else if (self.timeTable()[i].type() == "Break") {
				noOfBreaks++;
			} else {
				noOfStarStudyPeriod++;
			}
		}

		self.noOfStarStudyPeriod(noOfStarStudyPeriod);
		self.noOfPeriods(noOfPeriods);
		return noOfBreaks;
	});

	self.noofPeriods = ko.computed(function() {
		//console.log("calculating no of periods");

		return Number(self.noOfPeriods()) * Number(self.daysOfWeek().length);
	});

	self.totalDuration = ko.computed(function() {
		//console.log("calculating duration");
		var duration = 0;
		var fulldayDuration = retrunMin(self.endTiming()) - retrunMin(self.startTiming());
		for (var i = 0; i < self.timeTable().length; i++) {
			duration += Number(self.timeTable()[i].duration());
		}
		var num = Number(fulldayDuration - duration);
		//console.log("num: ", num, "full: ", fulldayDuration, "dur: ", duration);
		//var str = "Class Schedule(" + num + " Minutes unutilized)";
		self.unutilizedDuration(returnTimeFormat(num));

		return duration;
	});
	/* Will Return Minutes */
	function retrunMin(value) {
		//console.log("value: ", value);
		var min;
		var _time;
		var timeArr;
		var h;
		/*	if (value.indexOf("AM") != -1) {
		 var _time = value.replace("AM", "");
		 var timeArr = _time.split(":");

		 h = timeArr[0] == 12 ? 0 : timeArr[0];
		 min = Number(h) * 60 + Number(timeArr[1])
		 } else {
		 _time = value.replace("PM", "");
		 timeArr = _time.split(":");
		 h = timeArr[0] == 12 ? 0 : timeArr[0];
		 min = Number(Number(h) * 60 + Number(timeArr[1]) + 720)
		 }
		 */
		timeArr = value.split(":");
		min = Number(Number(timeArr[0]) * 60 + Number(timeArr[1]));
		//console.log("min: ", min);
		return min;
	}

	function returnTimeFormat(value) {

		var hour;
		var min;
		if (String(value).indexOf("-") != -1)// Negative
		{
			var _time = Number(String(value).replace("-", ""));

			hour = Math.floor(_time / 60);
			min = Number(_time % 60);

			min = Number(min) < 10 ? "0" + min : min;
			hour = Number(hour) < 10 ? "-0" + hour : "-" + hour;
		} else {
			hour = Math.floor(value / 60);
			min = Number(value % 60);

			hour = Number(hour) < 10 ? "0" + hour : hour;
			min = Number(min) < 10 ? "0" + min : min;
		}

		/*	hour = Number(hour) < 10 && 0 < ? "0" + hour :hour;
		 min = Number(min) < 10 ? "0" + min : min;
		 */
		return hour + ":" + min;
	};

	var isDataObject = typeof data == "object";
	if (data != "" && data != undefined) {

		for (var i = 0; i < data.daysOfWeek.length; i++) {
			for (var j = 0; j < self.weekDays().length; j++) {
				if (data.daysOfWeek[i].day == self.weekDays()[j].day()) {
					self.weekDays()[j].isSelected(true);
					break;
				}
			}
		}

		for (var k = 0; k < data.timeTable.length; k++) {
			self.timeTable.push(new periodBreakModel(data.timeTable[k]));
		}

		for (var l = 0; l < data.weekExceptions.length; l++) {
			self.weekExceptions.push(new dayExceptionModel(data.weekExceptions[l], self.daysOfWeek()));
		}
	}

	if (self.timeTable().length == 0) {
		self.timeTable.push(new periodBreakModel(""));
	}

	self.unutilizedDuration.subscribe(function(item) {
		//console.log("unutilizedDuration:", item);

		if (item.indexOf("-") !== -1) {
			isOverUilized = true;
			//alert("Exceded Utilization time");
			scheduleVM.openErrorDialog("Utilization Time", "Exceded Utilization time");
		} else {
			isOverUilized = false;
		}
	});
	//self.weekExceptions.push(new dayExceptionModel(""));
	//callCustomInit();

	/* To hide Error messages upfront  START*/
	var vm = ko.validation.group(scheduleVM);
	vm.showAllMessages(false);
	/* To hide Error messages upfront  END*/

};
var periodBreakModel = function(data) {
	var self = this;

	self.sno = ko.observable(0);
	self.type = ko.observable(data.type || "Period");
	//console.log("data.type :: ", data.type);
	self.duration = ko.observable(data.duration || 0);
	self.extraSno = function(item) {
		/*read:function(){
		//console.log("read",self.sno());
		return self.sno();
		},*/

		//console.log("item", item);
		self.sno(item);
		//console.log("sno:", self.sno());

		return self.sno();
	};

};
var applicableDay = function(data) {
	var self = this;

	self.title = ko.observable(data.title || "");
	self.day = ko.observable(data.day || "");
	self.isSelected = ko.observable(data.isSelected || false);

};
var dayExceptionModel = function(data, daysOfWeek) {
	var self = this;

	self.every = ko.observable(data.every || false);
	self.first = ko.observable(data.first || false);
	self.second = ko.observable(data.second || false);
	self.third = ko.observable(data.third || false);
	self.fourth = ko.observable(data.fourth || false);
	self.fifth = ko.observable(data.fifth || false);
	self.computedDay = ko.observable().extend({
		required : true
	});
	;

	if (daysOfWeek != undefined && daysOfWeek != "") {
		//console.log("----> daysOfWeek:", daysOfWeek);
		for (var i = 0; i < daysOfWeek.length; i++) {
			if (daysOfWeek[i].day() == data.day) {
				//console.log("-------->");
				self.computedDay(daysOfWeek[i] || "");
				break;
			}
		}
	}
	self.day = ko.computed(function() {
		if (self.computedDay() == undefined || self.computedDay() == "") {
			return "";
		} else {
			return self.computedDay().day();
		}
	});
};
/* Delete Handler */
var deleteViewModel = function() {
	var self = this;

	self.currentItem = ko.observable();
	self.parentItem = ko.observable();
	self.type = ko.observable();
	self.confirmationText = ko.observable("Do you want to delete?");

	self.deleteItem = function() {
		//console.log("deleting schedule:", self.currentItem().scheduleId());
		showLoader(true, TYPE_DELETING);
		jQuery.ajax({
			data : {
				scheduleId : self.currentItem().scheduleId()
			},
			url : baseOperationUrl + "deleteSecPlanSchedule",
			type : "post",
			success : function(result) {
				//console.log("result", result);

				if (result == "true") {
					var index = self.parentItem().scheduleList().indexOf(self.currentItem());
					self.parentItem().scheduleList.splice(index, 1);
				} else if (result == "hasDependency") {
					showLoader(false);
					//alert("Shifts are created based on current Schedule, Please remove corresponding Shifts to delete current Schedule ");
					scheduleVM.openErrorDialog("Shifts to Delete", "Shifts are created based on current Schedule, Please remove corresponding Shifts to delete current Schedule ");

				}
				showLoader(false);
			},
			error : function(jqXHR, textStatus, errorThrown) {
				//console.log("error");
				//showLoader(false);
			}
		});

		$("#dialog-confirmScheduleDelete").dialog("close");
	};

	self.cancelItem = function() {
		//console.log("------> cancel delete item");
		$("#dialog-confirmScheduleDelete").dialog("close");

		//self.confirmationText("Do you want to delete?");
	};
};

function fetchSchedules(_sectionId) {
	showLoader(true, TYPE_LOADING);
	jQuery.ajax({
		data : {
			sectionId : _sectionId
		},
		url : baseOperationUrl + "getSecPlanSchedules",
		type : "post",
		success : function(result) {
			//console.log("result ::: ", result);

			for (var i = 0; i < result.length; i++) {
				scheduleVM.scheduleList.push(new createScheduleModel(result[i]));

			}
			showLoader(false);
		},
		error : function(jqXHR, textStatus, errorThrown) {
			//console.log("error");
		}
	});
}

function deleteScheduleById(_scheduleId) {
	showLoader(true, TYPE_DELETING);
	jQuery.ajax({
		data : {
			scheduleId : _scheduleId
		},
		url : baseOperationUrl + "deleteSecPlanSchedule",
		type : "post",
		success : function(result) {
			//console.log("result", result);
			showLoader(false);
		},
		error : function(jqXHR, textStatus, errorThrown) {
			//console.log("error");
			//showLoader(false);
		}
	});
}

function callCustomInit() {
	//console.log("console call custom");

	if (!isInitialised) {
		Custom.init();
		isInitialised = true;
	}

}

$(function() {
	//console.log("Document Ready");
	//ko.applyBindings(new scheduleViewModel(),document.getElementById("tabs-1"));
	/* Commented For Integration START
	 scheduleVM = new scheduleViewModel()
	 ko.applyBindings(scheduleVM,document.getElementById("tabs-1"));
	 Commented For Integration END
	 $("#add-Schedule").dialog({
	 autoOpen : false,
	 width : 650,
	 modal : true
	 });
	 fetchSchedules(sectionId);*/

});
